Skip to content

Conversation

@lanza
Copy link
Member

@lanza lanza commented Nov 20, 2025

Stack from ghstack (oldest at bottom):

This commit implements basic thread-local storage support in ClangIR:

  1. Added EmitThreadLocalVarDeclLValue() method to CIRGenCXXABI interface
    to handle thread-local variable access in an ABI-specific way.

  2. Implemented EmitThreadLocalVarDeclLValue() in CIRGenItaniumCXXABI that:

    • Accesses thread-local variables directly using their GlobalOp
    • Relies on the 'tls_dyn' attribute on GlobalOp for TLS semantics
    • Handles both value and reference types correctly
    • Defers complex TLS wrapper function support to future work
  3. Modified CIRGenExpr.cpp to call the ABI method instead of asserting
    when encountering TLS_Dynamic variables.

  4. Added CIRGenModule::getAddrOfGlobalVar() helper for retrieving
    global variable addresses.

  5. Added comprehensive test coverage in thread-local.cpp that verifies:

    • Basic thread_local variables with constant initialization
    • GNU-style __thread variables - Function-local thread_local static variables
    • Reading from and writing to thread_local variables
    • Extern thread_local variable declarations
    • Correct CIR generation with tls_dyn attribute
    • Proper LLVM IR lowering to @llvm.threadlocal.address intrinsic

The implementation takes a simplified approach for now, relying on the
GlobalOp's thread_local attribute rather than generating wrapper functions.
This is sufficient for variables with trivial initialization. Future work
may add full wrapper function support for complex dynamic initialization.

[ghstack-poisoned]
lanza added a commit that referenced this pull request Nov 20, 2025
This commit implements basic thread-local storage support in ClangIR:

1. Added EmitThreadLocalVarDeclLValue() method to CIRGenCXXABI interface
   to handle thread-local variable access in an ABI-specific way.

2. Implemented EmitThreadLocalVarDeclLValue() in CIRGenItaniumCXXABI that:
   - Accesses thread-local variables directly using their GlobalOp
   - Relies on the 'tls_dyn' attribute on GlobalOp for TLS semantics
   - Handles both value and reference types correctly
   - Defers complex TLS wrapper function support to future work

3. Modified CIRGenExpr.cpp to call the ABI method instead of asserting
   when encountering TLS_Dynamic variables.

4. Added CIRGenModule::getAddrOfGlobalVar() helper for retrieving
   global variable addresses.

5. Added comprehensive test coverage in thread-local.cpp that verifies:
   - Basic thread_local variables with constant initialization
   - GNU-style __thread variables  - Function-local thread_local static variables
   - Reading from and writing to thread_local variables
   - Extern thread_local variable declarations
   - Correct CIR generation with tls_dyn attribute
   - Proper LLVM IR lowering to llvm.threadlocal.address intrinsic

The implementation takes a simplified approach for now, relying on the
GlobalOp's thread_local attribute rather than generating wrapper functions.
This is sufficient for variables with trivial initialization. Future work
may add full wrapper function support for complex dynamic initialization.


ghstack-source-id: 65ab4e1
Pull-Request: #1996
[ghstack-poisoned]
lanza added a commit that referenced this pull request Nov 20, 2025
This commit implements basic thread-local storage support in ClangIR:

1. Added EmitThreadLocalVarDeclLValue() method to CIRGenCXXABI interface
   to handle thread-local variable access in an ABI-specific way.

2. Implemented EmitThreadLocalVarDeclLValue() in CIRGenItaniumCXXABI that:
   - Accesses thread-local variables directly using their GlobalOp
   - Relies on the 'tls_dyn' attribute on GlobalOp for TLS semantics
   - Handles both value and reference types correctly
   - Defers complex TLS wrapper function support to future work

3. Modified CIRGenExpr.cpp to call the ABI method instead of asserting
   when encountering TLS_Dynamic variables.

4. Added CIRGenModule::getAddrOfGlobalVar() helper for retrieving
   global variable addresses.

5. Added comprehensive test coverage in thread-local.cpp that verifies:
   - Basic thread_local variables with constant initialization
   - GNU-style __thread variables  - Function-local thread_local static variables
   - Reading from and writing to thread_local variables
   - Extern thread_local variable declarations
   - Correct CIR generation with tls_dyn attribute
   - Proper LLVM IR lowering to llvm.threadlocal.address intrinsic

The implementation takes a simplified approach for now, relying on the
GlobalOp's thread_local attribute rather than generating wrapper functions.
This is sufficient for variables with trivial initialization. Future work
may add full wrapper function support for complex dynamic initialization.

ghstack-source-id: 2a8fafc
Pull-Request: #1996
@lanza lanza closed this Nov 20, 2025
@lanza lanza reopened this Nov 20, 2025
[ghstack-poisoned]
lanza added a commit that referenced this pull request Nov 20, 2025
This commit implements thread-local storage support in ClangIR:

1. Added EmitThreadLocalVarDeclLValue() method to CIRGenCXXABI interface
   to handle thread-local variable access in an ABI-specific way.

2. Implemented EmitThreadLocalVarDeclLValue() in CIRGenItaniumCXXABI that:
   - Accesses thread-local variables using cir.get_global thread_local
   - Relies on LLVM lowering to insert @llvm.threadlocal.address intrinsics
   - Handles both value and reference types correctly
   - Uses ClangIR's declarative approach instead of wrapper functions

3. Modified CIRGenExpr.cpp to call the ABI method for TLS_Dynamic variables.

4. Added CIRGenModule::getAddrOfGlobalVar() helper for retrieving
   global variable addresses.

5. Added comprehensive test coverage in thread-local.cpp that verifies:
   - Basic thread_local variables with constant initialization
   - GNU-style __thread variables
   - Function-local thread_local static variables
   - Reading from and writing to thread_local variables
   - Extern thread_local variable declarations
   - Correct CIR generation with tls_dyn attribute
   - Proper LLVM IR lowering to llvm.threadlocal.address intrinsic

ClangIR's approach differs from traditional CodeGen: instead of creating
wrapper functions (_ZTW*) in the IR, ClangIR marks GlobalOps with tls_dyn
and relies on LLVM lowering to insert @llvm.threadlocal.address intrinsics.
This achieves correct TLS semantics while maintaining ClangIR's higher-level
representation.

ghstack-source-id: d912c08
Pull-Request: #1996
[ghstack-poisoned]
lanza added a commit that referenced this pull request Nov 20, 2025
This commit implements thread-local storage support in ClangIR:

1. Added EmitThreadLocalVarDeclLValue() method to CIRGenCXXABI interface
   to handle thread-local variable access in an ABI-specific way.

2. Implemented EmitThreadLocalVarDeclLValue() in CIRGenItaniumCXXABI that:
   - Accesses thread-local variables using cir.get_global thread_local
   - Relies on LLVM lowering to insert @llvm.threadlocal.address intrinsics
   - Handles both value and reference types correctly
   - Uses ClangIR's declarative approach instead of wrapper functions

3. Modified CIRGenExpr.cpp to call the ABI method for TLS_Dynamic variables.

4. Added CIRGenModule::getAddrOfGlobalVar() helper for retrieving
   global variable addresses.

5. Added comprehensive test coverage in thread-local.cpp that verifies:
   - Basic thread_local variables with constant initialization
   - GNU-style __thread variables
   - Function-local thread_local static variables
   - Reading from and writing to thread_local variables
   - Extern thread_local variable declarations
   - Correct CIR generation with tls_dyn attribute
   - Proper LLVM IR lowering to llvm.threadlocal.address intrinsic

ClangIR's approach differs from traditional CodeGen: instead of creating
wrapper functions (_ZTW*) in the IR, ClangIR marks GlobalOps with tls_dyn
and relies on LLVM lowering to insert @llvm.threadlocal.address intrinsics.
This achieves correct TLS semantics while maintaining ClangIR's higher-level
representation.

ghstack-source-id: 267f175
Pull-Request: #1996
Copy link
Member

@bcardosolopes bcardosolopes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall good, thanks! Some nits and ready to go

// directly or require access through a thread wrapper function.
virtual bool usesThreadWrapperFunction(const VarDecl *VD) const = 0;

virtual LValue EmitThreadLocalVarDeclLValue(CIRGenFunction &CGF,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

camelBack here and everyelse it makes sense

return !isEmittedWithConstantInitializer(VD) || mayNeedDestruction(VD);
}

LValue EmitThreadLocalVarDeclLValue(CIRGenFunction &CGF, const VarDecl *VD,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

llvm::DenseSet<clang::GlobalDecl> DiagnosedConflictingDefinitions;

/// thread_local variables defined or used in this TU.
std::vector<const clang::VarDecl *> CXXThreadLocals;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be lowercase too!

[ghstack-poisoned]
lanza added a commit that referenced this pull request Nov 21, 2025
This commit implements thread-local storage support in ClangIR:

1. Added EmitThreadLocalVarDeclLValue() method to CIRGenCXXABI interface
   to handle thread-local variable access in an ABI-specific way.

2. Implemented EmitThreadLocalVarDeclLValue() in CIRGenItaniumCXXABI that:
   - Accesses thread-local variables using cir.get_global thread_local
   - Relies on LLVM lowering to insert @llvm.threadlocal.address intrinsics
   - Handles both value and reference types correctly
   - Uses ClangIR's declarative approach instead of wrapper functions

3. Modified CIRGenExpr.cpp to call the ABI method for TLS_Dynamic variables.

4. Added CIRGenModule::getAddrOfGlobalVar() helper for retrieving
   global variable addresses.

5. Added comprehensive test coverage in thread-local.cpp that verifies:
   - Basic thread_local variables with constant initialization
   - GNU-style __thread variables
   - Function-local thread_local static variables
   - Reading from and writing to thread_local variables
   - Extern thread_local variable declarations
   - Correct CIR generation with tls_dyn attribute
   - Proper LLVM IR lowering to llvm.threadlocal.address intrinsic

ClangIR's approach differs from traditional CodeGen: instead of creating
wrapper functions (_ZTW*) in the IR, ClangIR marks GlobalOps with tls_dyn
and relies on LLVM lowering to insert @llvm.threadlocal.address intrinsics.
This achieves correct TLS semantics while maintaining ClangIR's higher-level
representation.

ghstack-source-id: 0a94a40
Pull-Request: #1996
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants